package com.bdtop.dbl.bluetooth;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;

import com.bdtop.dbl.CrashHandler;
import com.bdtop.dbl.utils.DBLDebug;
import com.bdtop.dbl.utils.DblUtils;
import com.bdtop.dbl.utils.Preferences;
import com.bdtop.dbl.utils.SystemUtils;

@SuppressLint("DefaultLocale")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class BluetoothLeService extends Service {

	public final static String ACTION_GATT_RETRY_CONNECT = "com.dbl.bluetooth.le.ACTION_GATT_RETRY_CONNECT";
	public final static String ACTION_GATT_CONNECTED = "com.dbl.bluetooth.le.ACTION_GATT_CONNECTED";
	public final static String ACTION_GATT_DISCONNECTED = "com.dbl.bluetooth.le.ACTION_GATT_DISCONNECTED";
	public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.dbl.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
	public final static String ACTION_DATA_AVAILABLE = "com.dbl.bluetooth.le.ACTION_DATA_AVAILABLE";
	public final static String ACTION_READ_REMOTE_RSSI = "com.dbl.bluetooth.le.ACTION_READ_REMOTE_RSSI";
	public final static String ACTION_READ_REMOTE_DISTANCE = "com.dbl.bluetooth.le.ACTION_READ_REMOTE_DISTANCE";
	public final static String EXTRA_DATA = "com.dbl.bluetooth.le.EXTRA_DATA";
	public final static UUID UUID_HEART_RATE_MEASUREMENT = DblGattAttributes.HEART_RATE_MEASUREMENT;

	public static final int STATE_DISCONNECTED = 0;
	public static final int STATE_CONNECTING = 1;
	public static final int STATE_CONNECTED = 2;

	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private  BluetoothGatt mBluetoothGatt;
	private  String mBluetoothDeviceAddress;
	private int mConnectionState = STATE_DISCONNECTED;
	private boolean disconnectPositive = false;
	private long deviceConnectedTime;
	private long disconnectedAlertTime;
	private long distanceAlertTime;

	private static BluetoothGattCallback mGattCallback;
	
	private int test_flag = 2;
	
	@Override public void onCreate() {
		DBLDebug.logd("BluetoothLeService onCreate test_flag:" + test_flag);
		super.onCreate();
	}

	private void initCallback() {
		if (mGattCallback == null) {
			DBLDebug.logd("BluetoothLeService new mGattCallback");
			mGattCallback = new BluetoothGattCallback() {
				@Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
					if (newState == BluetoothProfile.STATE_CONNECTED) {
						recordConnectInfo("GattCallback onConnectionStateChange() STATE_CONNECTED : 蓝牙连接!");
						DBLDebug.logd("BluetoothLeService GATT server connected");
						deviceConnectedTime = System.currentTimeMillis();
						DBLDebug.loge("mConnectionState = STATE_CONNECTED");
						mConnectionState = STATE_CONNECTED;
						broadcastUpdate(ACTION_GATT_CONNECTED);

						// Attempts to discover services after successful
						// connection.
						DBLDebug.logd("Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
						getSupportedGattServices();

						// 2015 new api
						mHandler.removeCallbacks(fixConnectingNoResponse);
						resetDistanceList(0);
						requestSetDefaultContorlParams();
						initProtectRule();
						startGetRssiTimer();
						stopTryReconnectTask();
					} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
						recordConnectInfo("GattCallback onConnectionStateChange() STATE_DISCONNECTED : 蓝牙断开! [主动？" + disconnectPositive
								+ "]");
						DBLDebug.logd("BluetoothLeService GATT server disconnected : 主动断开？" + disconnectPositive);
						DBLDebug.loge("mConnectionState = STATE_DISCONNECTED");
						mConnectionState = STATE_DISCONNECTED;
						broadcastUpdate(ACTION_GATT_DISCONNECTED);

						// 2015 new api
						mHandler.removeCallbacks(fixConnectingNoResponse);
						stopGetRssiTimer();

						mBluetoothDeviceAddress = "";
						if (disconnectPositive) {
							// disconnectPositive 为 true 表示积极点击断开按钮
							disconnectPositive = false;
							
						} else {
							dealProtectDisconnect();

							mBluetoothGatt.disconnect();
							close();

							startTryReconnectTask(); // 被动断开连接， 尝试重新连接
						}
					} else {
						recordConnectInfo("GattCallback onConnectionStateChange() ? : 未处理的状态 newState : " + newState);
					}

				}

				@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) {
					if (status == BluetoothGatt.GATT_SUCCESS) {
						broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
					} else {
						DBLDebug.logd("BluetoothLeService onServicesDiscovered received: " + status);
					}
				}

				@Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
					if (status == BluetoothGatt.GATT_SUCCESS) {
						broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
					}
				}

				@Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
					broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
				}

				@Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
				}
			};
		}
	}

	@Override public int onStartCommand(Intent intent, int flags, int startId) {
		DBLDebug.logd("BluetoothLeService onStartCommand() test_flag:" + test_flag);
		DBLDebug.loge("BluetoothLeService onStartCommand() mGattCallback:" + mGattCallback);
		
		if (!SystemUtils.supportBLE(BluetoothLeService.this)) {
			recordConnectInfo("onStartCommand : 手机不支持蓝牙功能");
			DBLDebug.loge("BluetoothLeService onStartCommand() init fail!!!!不支持蓝牙!!!");
			check2StopService();
			return START_NOT_STICKY;
		}

		if (!initialize()) {
			recordConnectInfo("onStartCommand : 蓝牙组件初始化失败");
			DBLDebug.loge("BluetoothLeService onStartCommand() init fail!!!!!初始化失败!!!");
			mBluetoothDeviceAddress = "";
			check2StopService();
		}

		initCallback();

		// tryConnectLastBluetoothDevice();

		return START_STICKY;
	}

	private boolean initialize() {
		if (mBluetoothManager == null) {
			mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
			if (mBluetoothManager == null) {
				DBLDebug.logd("BluetoothLeService Unable to initialize BluetoothManager.");
				return false;
			}
		}
		mBluetoothAdapter = mBluetoothManager.getAdapter();
		if (mBluetoothAdapter == null) {
			DBLDebug.logd("BluetoothLeService Unable to obtain a BluetoothAdapter.");
			return false;
		}
		recordConnectInfo("onStartCommand : 蓝牙组件初始化完成");
		DBLDebug.logd("BluetoothLeService init success");
		return true;
	}

	public void tryConnectLastBluetoothDevice() {
		
		String address = Preferences.getLastConnectBluetoothDeviceAddress(BluetoothLeService.this);
		DBLDebug.loge("BluetoothLeService tryConnectLastBluetoothDevice. [address: " + address + "]");
		if (!isConnected() && !TextUtils.isEmpty(address)) {
			recordConnectInfo("tryConnectLastBluetoothDevice() : 尝试重新连接蓝牙: " + address);
			DBLDebug.loge("BluetoothLeService. [address: " + address + "]");
			connect(address);
			broadcastUpdate(ACTION_GATT_RETRY_CONNECT);
		} else if (!isConnected() && !isConnecting()) {
			recordConnectInfo("tryConnectLastBluetoothDevice() : 停止重新连接，断开并且关闭蓝牙服务");
			DBLDebug.loge("BluetoothLeService stopself() address null");
			stopTryReconnectTask();
			stopGetRssiTimer();
			stopSelf();
		}
	}

	public void check2StopService() {
		DBLDebug.loge("BluetoothLeService check2StopService()");
		if (TextUtils.isEmpty(mBluetoothDeviceAddress)) {
			if (mBluetoothGatt != null) {
				mBluetoothGatt.disconnect();
			}
			close();
			stopTryReconnectTask();
			stopGetRssiTimer();
			stopSelf();
		}
	}
	
	public void releaseGatt() {
		DBLDebug.loge("BluetoothLeService releaseGatt()");
		disconnect();
		if (TextUtils.isEmpty(mBluetoothDeviceAddress)) {
			if (mBluetoothGatt != null) {
				mBluetoothGatt.disconnect();
			}
			close();
			stopTryReconnectTask();
			stopGetRssiTimer();
		}
	}
	
	public boolean isConnected() {
		return mConnectionState == STATE_CONNECTED;
	}

	public boolean isConnecting() {
		return mConnectionState == STATE_CONNECTING;
	}

	public int getConnectionState() {
		return mConnectionState;
	}

	public boolean isEnable() {
		if (mBluetoothAdapter == null) {
			DBLDebug.logd("BluetoothLeService isEnable() bluetoothAdapter null");
			return false;
		}
		return mBluetoothAdapter.isEnabled();
	}

	public String getBluetoothDeviceAddress() {
		return mBluetoothDeviceAddress;
	}

	public void startLeScan(BluetoothAdapter.LeScanCallback callback) {
		if (callback == null) {
			DBLDebug.loge("BluetoothLeService startLeScan() callback null");
			return;
		}
		if (mBluetoothAdapter == null) {
			DBLDebug.logd("BluetoothLeService startLeScan() bluetoothAdapter null");
			return;
		}
		recordConnectInfo("startLeScan() : 开始扫描蓝牙设备");
		
		DBLDebug.logd("reg startLeScan 开始扫描蓝牙设备");
		mBluetoothAdapter.startLeScan(callback);
	}
	

	public void stopLeScan(BluetoothAdapter.LeScanCallback callback) {
		if (callback == null) {
			DBLDebug.loge("BluetoothLeService stopLeScan() callback null");
			return;
		}
		if (mBluetoothAdapter == null) {
			DBLDebug.logd("BluetoothLeService stopLeScan() bluetoothAdapter null");
			return;
		}
		recordConnectInfo("stopLeScan() : 停止扫描蓝牙设备");
		
		mBluetoothAdapter.stopLeScan(callback);
	}

	@Override public void onDestroy() {
		super.onDestroy();
		DBLDebug.logd("BluetoothLeService onDestroy() test_flag:" + test_flag);
		
		requestDisconnect();
		stopTryReconnectTask();
		
		if(mBluetoothGatt != null){
			mBluetoothGatt.disconnect();
			close();	
		}
	}

	private void broadcastUpdate(final String action) {
		final Intent intent = new Intent(action);
		sendBroadcast(intent);
	}

	private void broadcastRssiUpdate(final String action, int rssi) {
		final Intent intent = new Intent(action);
		intent.putExtra("rssi", rssi);
		sendBroadcast(intent);
	}

	private void broadcastDistanceUpdate(final String action, double distance) {
		final Intent intent = new Intent(action);
		intent.putExtra("distance", distance);
		sendBroadcast(intent);
	}

	private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
		final Intent intent = new Intent(action);
		// This is special handling for the Heart Rate Measurement profile. Data
		// parsing is
		// carried out as per profile specifications:
		// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
		if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
			int flag = characteristic.getProperties();
			int format = -1;
			if ((flag & 0x01) != 0) {
				format = BluetoothGattCharacteristic.FORMAT_UINT16;
				DBLDebug.logd("Heart rate format UINT16.");
			} else {
				format = BluetoothGattCharacteristic.FORMAT_UINT8;
				DBLDebug.logd("Heart rate format UINT8.");
			}
			final int heartRate = characteristic.getIntValue(format, 1);
			DBLDebug.logd(String.format("Received heart rate: %d", heartRate));
			intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
		} else {
			// For all other profiles, writes the data formatted in HEX.
			final byte[] data = characteristic.getValue();
			if (data != null && data.length > 0) {
				final StringBuilder stringBuilder = new StringBuilder(data.length);
				for (byte byteChar : data)
					stringBuilder.append(String.format("%02X ", byteChar));
				intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
			}
		}
		sendBroadcast(intent);
	}

	public class LocalBinder extends Binder {
		public BluetoothLeService getService() {
			return BluetoothLeService.this;
		}
	}

	@Override public IBinder onBind(Intent intent) {
		return mBinder;
	}

	@Override public boolean onUnbind(Intent intent) {
		// After using a given device, you should make sure that
		// BluetoothGatt.close() is called
		// such that resources are cleaned up properly. In this particular
		// example, close() is
		// invoked when the UI is disconnected from the Service.

		// close(); // 20150228 do not close
		return super.onUnbind(intent);
	}

	private final IBinder mBinder = new LocalBinder();

	/**
	 * Connects to the GATT server hosted on the Bluetooth LE device.
	 * 
	 * @param address
	 *            The device address of the destination device.
	 * @return Return true if the connection is initiated successfully. The
	 *         connection result is reported asynchronously through the
	 *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
	 *         callback.
	 */
	public boolean connect(final String address) {
		if (mBluetoothAdapter == null) {
			DBLDebug.loge("BluetoothLeService connect() BluetoothAdapter not initialized ");
			return false;
		}
		if (address == null) {
			DBLDebug.loge("BluetoothLeService connect() unspecified address.");
			return false;
		}
		DBLDebug.loge("BluetoothLeService connect() mBluetoothDeviceAddress:" + mBluetoothDeviceAddress);
		DBLDebug.loge("BluetoothLeService connect() mBluetoothGatt:" + mBluetoothGatt);
		// Previously connected device. Try to reconnect.
		if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
			DBLDebug.logd("BluetoothLeService Trying to use an existing mBluetoothGatt for connection.");
			if (mBluetoothGatt.connect()) {
				recordConnectInfo("connect() : 根据已创建的bluetoothGatt重新连接蓝牙：" + mBluetoothDeviceAddress);
				DBLDebug.loge("mConnectionState = STATE_CONNECTING");
				mConnectionState = STATE_CONNECTING;
				mHandler.postDelayed(fixConnectingNoResponse, 10000);
				return true;
			} else {
				recordConnectInfo("connect() : 根据已创建的bluetoothGatt重新连接蓝牙：失败！！关闭bluetoothGatt");
				close();
				return false;
			}
		}

		final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
		if (device == null) {
			DBLDebug.logd("BluetoothLeService Device not found.  Unable to connect.");
			return false;
		}
		// We want to directly connect to the device, so we are setting the
		// autoConnect
		// parameter to false.
		mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
		recordConnectInfo("connect() : 创建新的bluetoothGatt连接蓝牙：" + mBluetoothDeviceAddress);
		DBLDebug.logd("BluetoothLeService Trying to create a new connection.[" + address + "]");
		mBluetoothDeviceAddress = address;

		Preferences.saveLastConnectBluetoothDeviceAddress(BluetoothLeService.this, mBluetoothDeviceAddress);
		DBLDebug.loge("mConnectionState = STATE_CONNECTING");
		mConnectionState = STATE_CONNECTING;
		mHandler.postDelayed(fixConnectingNoResponse, 10000);
		return true;
	}

	//
	private Runnable fixConnectingNoResponse = new Runnable() {
		@Override public void run() {
			if (isConnecting()) {
				disconnectPositive = true;
				recordConnectInfo("蓝牙连接超时无响应(10秒)，主动断开蓝牙！ bluetoothGatt.disconnect()");
				mBluetoothGatt.disconnect();
				close();
				// disconenct后，mGattCallback STATE_DISCONNECTED 不被触发。
				DBLDebug.loge("mConnectionState = STATE_DISCONNECTED");
				mConnectionState = STATE_DISCONNECTED;
				mBluetoothDeviceAddress = "";
				Preferences.saveLastConnectBluetoothDeviceAddress(BluetoothLeService.this, mBluetoothDeviceAddress);
				broadcastUpdate(ACTION_GATT_DISCONNECTED);
			}
		}
	};

	/**
	 * Disconnects an existing connection or cancel a pending connection. The
	 * disconnection result is reported asynchronously through the
	 * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
	 * callback.
	 */
	public void disconnect() {
		stopGetRssiTimer();
		requestDisconnect();

		new Handler().postDelayed(new Runnable() {
			@Override public void run() {
				if (mBluetoothGatt == null) {
					DBLDebug.logd("BluetoothLeService disconnect mBluetoothGatt not initialized");
					return;
				}
				disconnectPositive = true;
				recordConnectInfo("主动断开蓝牙！ bluetoothGatt.disconnect()");
				mBluetoothGatt.disconnect();
				close();
				// disconenct后，mGattCallback STATE_DISCONNECTED 不被触发。
				DBLDebug.loge("BluetoothLeService mConnectionState = STATE_DISCONNECTED");
				mConnectionState = STATE_DISCONNECTED;
				mBluetoothDeviceAddress = "";
				Preferences.saveLastConnectBluetoothDeviceAddress(BluetoothLeService.this, mBluetoothDeviceAddress);
				broadcastUpdate(ACTION_GATT_DISCONNECTED);
			}
		}, 1500);
	}

	/**
	 * After using a given BLE device, the app must call this method to ensure
	 * resources are released properly.
	 */
	public void close() {
		if (mBluetoothGatt == null) {
			return;
		}
		mBluetoothGatt.close();
		mBluetoothGatt = null;
		recordConnectInfo("close() : 关闭并释放 bluetoothGatt");
		recordConnectInfo("BluetoothLeService close() : 关闭并释放 bluetoothGatt");
		
	}

	private byte[] readFromRemoteDevice(UUID characteristicId) {
		if (mBluetoothGatt == null) {
			DBLDebug.loge("BluetoothLeService writeToRemoteDevice() mBluetoothGatt not initialized");
			return null;
		}
		BluetoothGattService service = mBluetoothGatt.getService(DblGattAttributes.SERVICE_BLE);
		DBLDebug.logd("BluetoothLeService writeToRemoteDevice() service:" + service);
		if (service != null) {
			BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicId);
			if (characteristic != null) {
				mBluetoothGatt.readCharacteristic(characteristic);
				if (characteristic.getValue() != null && characteristic.getValue().length > 0) {
					return characteristic.getValue();
				}
			}
		}
		return null;
	}

	private boolean writeToRemoteDevice(UUID characteristicId, byte[] value) {
		if (mBluetoothGatt == null) {
			DBLDebug.loge("BluetoothLeService writeToRemoteDevice() mBluetoothGatt not initialized");
			return false;
		}
		BluetoothGattService service = mBluetoothGatt.getService(DblGattAttributes.SERVICE_BLE);
		if (service != null) {
			BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicId);
			if (characteristic != null) {
				characteristic.setWriteType(1);
				characteristic.setValue(value);
				mBluetoothGatt.writeCharacteristic(characteristic);
				return true;
			}
			DBLDebug.loge("BluetoothLeService writeToRemoteDevice() characteristic:" + characteristic);
		}
		DBLDebug.loge("BluetoothLeService writeToRemoteDevice() service:" + service);
		return false;
	}

	@SuppressWarnings("unused") private void retryWrite(int tryTime, byte[] value) {
		DBLDebug.loge("retryWrite()");
		byte[] lastCmd = requestLastContorlParams();
		DBLDebug.loge("retryWrite() lastCmd " + lastCmd);
		boolean isWriteSuccess = DblUtils.isEq(lastCmd, value);
		DBLDebug.loge("to retryWrite ? " + !isWriteSuccess + ",tryTime:" + tryTime + ",lastCmd:" + lastCmd);
		if (!isWriteSuccess && tryTime > 0) {
			requestCall(--tryTime);
		}
	}

	public void requestCall(final int tryTime) {
		DBLDebug.logd("BluetoothLeService requestCall()");
		writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_CONTORL_CALL);
		recordConnectInfo("请求呼叫蓝牙设备1 requestCall()");

		mHandler.postDelayed(new Runnable() {
			@Override public void run() {
				recordConnectInfo("请求呼叫蓝牙设备2 requestCall()");
				// DBLDebug.loge("mHandler requestCall()");
				// retryWrite(tryTime, DblGattAttributes.VALUE_CONTORL_CALL);

				DBLDebug.logd("BluetoothLeService requestCall() ..");
				writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_CONTORL_CALL);
			}
		}, 100);
	}

	public void requestStopAlert(final int tryTime) {
		DBLDebug.logd("BluetoothLeService requestStopAlert()");
		writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_CONTORL_STOP_ALTER);
		recordConnectInfo("请求蓝牙设备停止报警  requestStopAlert()");
		mHandler.postDelayed(new Runnable() {
			@Override public void run() {
				recordConnectInfo("请求蓝牙设备停止报警2  requestStopAlert()");
				// DBLDebug.loge("mHandler requestStopAlert()");
				// retryWrite(tryTime,
				// DblGattAttributes.VALUE_CONTORL_STOP_ALTER);
				DBLDebug.logd("BluetoothLeService requestStopAlert() ..");
				writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_CONTORL_STOP_ALTER);
			}
		}, 100);
	}

	public void requestDisconnect() {
		recordConnectInfo("请求断开蓝牙设备  requestDisconnect()");
		DBLDebug.logd("BluetoothLeService requestDisconnect()");
		writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_DUANKAI);
	}

	public void requestSetDefaultContorlParams() {
		recordConnectInfo("请求设置蓝牙初始参数  requestSetDefaultContorlParams() { 0x01, 0x01, 0x00, 0x30 }");
		DBLDebug.logd("BluetoothLeService requestSetDefaultContorlParams()");
		writeToRemoteDevice(DblGattAttributes.PARAMS_CONTROL, DblGattAttributes.VALUE_CONTORL);
	}

	public boolean requestGetRssi() {
		recordConnectInfo("请求蓝牙信号信息  requestGetRssi() ");
//		DBLDebug.logd("BluetoothLeService requestGetRssi()");
		if (mBluetoothGatt == null) {
			DBLDebug.logd("BluetoothLeService writeToRemoteDevice() mBluetoothGatt not initialized");
			return false;
		}
		BluetoothGattService service = mBluetoothGatt.getService(DblGattAttributes.SERVICE_BLE);
		if (service != null) {
			BluetoothGattCharacteristic characteristic = service.getCharacteristic(DblGattAttributes.PARAMS_RSSI);
			if (characteristic != null) {
				mBluetoothGatt.readCharacteristic(characteristic);
				if (characteristic.getValue() != null && characteristic.getValue().length > 0) {
					mConnectionState = STATE_CONNECTED;
					int rssi = characteristic.getValue()[0];
					broadcastRssiUpdate(ACTION_READ_REMOTE_RSSI, rssi);

					double avgDistance = recordAndGetAvgDistance(DblUtils.distanceFromRssi(rssi));
					broadcastDistanceUpdate(ACTION_READ_REMOTE_DISTANCE, avgDistance);

					dealGetDistance(avgDistance);
//					DBLDebug.logd("BluetoothLeService rssi:" + rssi + ",avg distance:" + avgDistance);
					recordConnectInfo("请求蓝牙信号 : rssi : " + rssi + ",推算距离 : " + avgDistance);
					return true;
				} else {
					recordConnectInfo("请求蓝牙信号 : rssi : 读取失败");
					record2SDcard("请求蓝牙信号 : rssi : 读取失败");
				}
			} else {
				DBLDebug.logw("BluetoothLeService requestGetRssi() fail!characteristic:" + characteristic);
				recordConnectInfo("请求蓝牙信号信息  失败！characteristic :" + characteristic);
			}
		}
		recordConnectInfo("请求蓝牙信号信息  失败！service " + service);
		DBLDebug.logw("BluetoothLeService requestGetRssi() fail!service:" + service);
		return false;

	}

	public byte[] requestLastContorlParams() {
		DBLDebug.logd("BluetoothLeService requestLastContorlParams()");
		return readFromRemoteDevice(DblGattAttributes.PARAMS_CONTROL);
	}

	/**
	 * Retrieves a list of supported GATT services on the connected device. This
	 * should be invoked only after {@code BluetoothGatt#discoverServices()}
	 * completes successfully.
	 * 
	 * @return A {@code List} of supported services.
	 */
	public List<BluetoothGattService> getSupportedGattServices() {
		if (mBluetoothGatt == null)
			return null;

		return mBluetoothGatt.getServices();
	}

	/* 距离算法 取平均值 */
	private final int AVG_RECORD_COUNT = 4;
	private LinkedList<Double> distanceList = new LinkedList<Double>();

	private void resetDistanceList(double defaultDistance) {
		distanceList.clear();
		int time = AVG_RECORD_COUNT;
		while (time-- > 0) {
			distanceList.add(defaultDistance);
		}
	}

	private double recordAndGetAvgDistance(double distance) {
		if (distance < 0) {
			distance = 0;
		}
		if (distanceList.size() >= AVG_RECORD_COUNT) {
			distanceList.removeFirst();
		}
		distanceList.addLast(distance);

		double total = 0;
		for (double dis : distanceList) {
			total += dis;
		}
		return total / distanceList.size();
	}

	/* 排误算法 取第n次的超出范围 */
	private int SENSITIVITY_TIME = 2;
	private int sensitivity = 0;

	public void dealGetDistance(double distance) {
		distance = Math.abs(distance);
		if (isProtect) {
			if (System.currentTimeMillis() - distanceAlertTime < 10000) {
				recordConnectInfo("信号较差！！避免频繁报警,已经略过:" + (System.currentTimeMillis() - disconnectedAlertTime) + "毫秒");
				return; // 避免频繁报警
			}
			if (distance > mProtectDistance) {
				sensitivity = sensitivity + 1;
			} else {
				sensitivity = 0;
			}
//			DBLDebug.logd("BluetoothLeService dealDeviceDistance() sensitivity " + sensitivity);
			if (sensitivity > SENSITIVITY_TIME) {
				sensitivity = 0;
				// distanceAlertTime = System.currentTimeMillis(); //在stop里面设置

				recordConnectInfo("超出保护距离！！当前距离：" + distance + ",保护距离:" + mProtectDistance);
				startPlayMedia();
				BleDeviceWarningActivity.launch(this);
			}
		}
	}

	public void dealProtectDisconnect() {
		if (isProtect && isDisconnectProtect) {
			if (System.currentTimeMillis() - disconnectedAlertTime < 10000) {
				recordConnectInfo("信号丢失！！避免频繁报警,已经丢失:" + (System.currentTimeMillis() - disconnectedAlertTime) + "毫秒");
				return; // 避免频繁报警
			}
			if (System.currentTimeMillis() - deviceConnectedTime < 3000) {
				recordConnectInfo("信号丢失！！避免刚连接上的信号不稳定,已经丢失:" + (System.currentTimeMillis() - deviceConnectedTime) + "毫秒");
				return;// 避免误报 [刚连接信号不稳]
			}
			// 避免误报 连接信号不稳，有时候秒断]
			recordConnectInfo("信号丢失！！延时检查机制开启，避免误报 连接信号不稳!");
			mHandler.postDelayed(new Runnable() {
				@Override public void run() {
					if (!isConnected()) {
						recordConnectInfo("蓝牙未连接，信号丢失！！发起报警!");
						disconnectedAlertTime = System.currentTimeMillis();
						startPlayMedia();
						BleDeviceWarningActivity.launch(BluetoothLeService.this);
					}
				}
			}, 1000);
		}
	}

	private boolean isProtect = true;
	private int mProtectDistance = 0;
	private boolean isDisconnectProtect = true;
	private Timer mGetRssiTimer;
	private MediaPlayer mMediaPlayer = new MediaPlayer();
	private Handler mHandler = new Handler();
	private boolean isPlayMedia = false;

	public void initProtectRule() {
		if (!TextUtils.isEmpty(mBluetoothDeviceAddress)) {
			isProtect = Preferences.getBleDeviceFangdiu(this, mBluetoothDeviceAddress);
			mProtectDistance = Preferences.getBleDeviceFangdiuJuli(this, mBluetoothDeviceAddress);
			isDisconnectProtect = Preferences.getBleDeviceFangdiuDuankai(this, mBluetoothDeviceAddress);
		}
	}

	private class GetRssiTimerTask extends TimerTask {
		private int failTime = 0;

		@Override public void run() {
			failTime = requestGetRssi() ? 0 : failTime + 1;

			if (failTime > 10) {
				failTime = 0;
				stopGetRssiTimer();
			}
		}
	};

	public void startGetRssiTimer() {
		stopGetRssiTimer();
		mGetRssiTimer = new Timer();
		mGetRssiTimer.schedule(new GetRssiTimerTask(), 0, 1000);
	}

	public void stopGetRssiTimer() {
		if (mGetRssiTimer != null) {
			mGetRssiTimer.cancel();
			mGetRssiTimer.purge();
			mGetRssiTimer = null;
		}
	}

	public void startPlayMedia() {
		// isPlayMedia = true;
		if (!isPlayMedia) {
			Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
			try {
				mMediaPlayer.setDataSource(this, alert);
				mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
				mMediaPlayer.setLooping(true);
				mMediaPlayer.prepare();
				mMediaPlayer.start();
				isPlayMedia = true;
			} catch (Exception e) {
				DBLDebug.loge("BluetoothLeService startPlayMedia() fail");
			}
			mHandler.postDelayed(new Runnable() {
				@Override public void run() {
					stopPlayMedia();
				}
			}, 6000);
		}
	}

	public void stopPlayMedia() {
		try {
			mMediaPlayer.stop();
			mMediaPlayer.reset();
			isPlayMedia = false;
			distanceAlertTime = System.currentTimeMillis();
		} catch (Exception e) {
			DBLDebug.loge("BluetoothLeService stopPlayMedia() fail");
		}
	}

	/* 重连 */
	// private float tryInterval = 3;
	private int tryTime = 100;
	private Runnable runTryReconnect = new Runnable() {
		@Override public void run() {
			tryConnectLastBluetoothDevice();
			tryTime--;
			if (tryTime > 0) {
				mHandler.postDelayed(runTryReconnect, 3000);
			} else {
				stopTryReconnectTask();
				stopGetRssiTimer();
				stopSelf();
			}
		}
	};

	public void startTryReconnectTask() {
		stopTryReconnectTask();
		tryTime = 100;
		mHandler.post(runTryReconnect);
	}

	public void stopTryReconnectTask() {
		mHandler.removeCallbacks(runTryReconnect);
	}

	// test
	private final boolean is2RecordInfo = false;
	private LinkedList<String> connectInfo = new LinkedList<String>();
	@SuppressLint("SimpleDateFormat") private SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss.S");

	private synchronized void recordConnectInfo(String info) {
		if (is2RecordInfo) {
			info = sdf.format(new Date()) + " " + info;
			connectInfo.addLast(info);
			if (connectInfo.size() > 100) {
				connectInfo.removeFirst();
			}
		}
	}

	private void record2SDcard(String title) {
		if (is2RecordInfo) {
			if (!TextUtils.isEmpty(title)) {
				title = "[" + title + "]";
			}
			title = "蓝牙连接信息记录  " + title + sdf.format(new Date());
			final StringBuffer sb = new StringBuffer();
			for (String info : connectInfo) {
				sb.append(info).append("\n");
			}

			final String mTitle = title;

			mHandler.postDelayed(new Runnable() {
				@Override public void run() {
					new Thread(new Runnable() {
						@Override public void run() {
							CrashHandler.savaInfoToSD(BluetoothLeService.this, "随意找蓝牙信息记录", mTitle, sb.toString());
						}
					}).start();
				}
			}, 2000);
		}
	}

}
